<!--
 * @Author: 赵克强 huohuo625@163.com
 * @Date: 2023-10-23 09:22:47
 * @LastEditors: 赵克强 huohuo625@163.com
 * @LastEditTime: 2024-04-30 10:04:26
 * @FilePath: \hy-ui\src\views\app\appInfo\components\detail\dataModel\erModel\addOrEditModal.vue
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
-->
<template>
  <div class="erAddOrEditModal">
    <el-dialog
      :title="row ? '编辑' : '新增'"
      :visible.sync="open"
      width="90%"
      :before-close="close"
    >
      <div>
        <el-form
          ref="form"
          :model="form"
          label-width="120px"
          class="demo-ruleForm"
          :rules="rules"
        >
          <div class="box">
            <el-form-item label="ER模型名称" prop="name">
              <el-input
                v-model="form.name"
                clearable
                placeholder="请输入ER模型名称"
              />
            </el-form-item>
            <el-form-item label="ER模型标识" prop="mark">
              <el-input
                v-model="form.mark"
                clearable
                placeholder="请输入ER模型标识"
              />
            </el-form-item>
            <!-- <el-form-item label="排序" prop="sort">
          <el-input
            v-model="form.sort"
            clearable
            placeholder="请输入排序"
            type="number"
          />
        </el-form-item> -->
          </div>
        </el-form>
        <div>
          <el-button
            icon="el-icon-plus"
            @click="() => handleAddChild()"
            :disabled="tableData.length"
            size="small"
            >设置主表</el-button
          >
        </div>
        <div class="table">
          <el-table
            :data="tableData"
            border
            style="width: 100%"
            row-key="id"
            default-expand-all
            :tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
          >
            <el-table-column label="对象关系">
              <el-table-column label="表名称" align="left" min-width="300">
                <template slot-scope="scope">
                  <!-- {{ `${scope.row.remark}(${scope.row.tableName})` }} -->
                  {{ `${scope.row.formComment}(${scope.row.formCode})` }}
                </template>
              </el-table-column>
              <el-table-column
                prop="relation"
                label="关系"
                align="left"
                width="150"
              >
                <template slot-scope="scope">
                  <el-select
                    v-model="scope.row.relation"
                    placeholder="请选择"
                    v-if="scope.row.relation && scope.row.relation !== 'single'"
                  >
                    <el-option
                      v-for="item in dict.type.pt_app_er_model_structure"
                      :key="item.value"
                      :label="item.label"
                      :value="item.value"
                    >
                    </el-option>
                  </el-select>
                  <span v-else> 主表 </span>
                </template>
              </el-table-column>
              <el-table-column label="外键" align="left" min-width="500">
                <template slot-scope="scope"
                  ><div
                    v-if="scope.row.relation && scope.row.relation !== 'single'"
                  >
                    <el-select
                      v-model="scope.row.mainForeignKey"
                      placeholder="请选择"
                    >
                      <el-option
                        v-for="item in scope.row.optionsMain"
                        :key="item.field"
                        :label="item.label"
                        :value="item.field"
                      >
                      </el-option>
                    </el-select>
                    <span style="margin: 0 30px">对应</span>
                    <el-select
                      v-model="scope.row.subForeignKey"
                      placeholder="请选择"
                    >
                      <el-option
                        v-for="item in scope.row.optionsChild"
                        :key="item.field"
                        :label="item.label"
                        :value="item.field"
                      >
                      </el-option>
                    </el-select>
                    <el-button
                      type="danger"
                      icon="el-icon-delete"
                      size="mini"
                      style="margin-left: 10px"
                      @click="handleDelete(scope.row, 'type')"
                    ></el-button>
                  </div>
                </template>
              </el-table-column>
              <el-table-column label="操作" align="center" width="200">
                <template slot-scope="scope"
                  ><div>
                    <el-button
                      type="text"
                      @click="() => handleAddChild(scope.row)"
                      >添加子表</el-button
                    >
                    <el-button
                      type="text"
                      @click="handleDelete(scope.row)"
                      style="color: #f56c6c"
                      >删除</el-button
                    >
                  </div>
                </template>
              </el-table-column>
            </el-table-column>
          </el-table>
        </div>
      </div>
      <span slot="footer" class="dialog-footer">
        <el-button @click="close">取 消</el-button>
        <el-button type="primary" @click="handleSubmit">确 定</el-button>
      </span>
    </el-dialog>
    <settingMainTable
      :settingTableOPen="settingTableOPen"
      :appId="appId"
      :close="closeModel"
      :settingTableClose="settingTableClose"
      v-if="settingTableOPen"
      :btnLoading="btnLoading"
    />
  </div>
</template>

<script>
import settingMainTable from "./settingMainTable.vue";
import { uuid } from "vue-uuid";
import {
  appErModelDetail,
  appErModelAdd,
  appErModelUpdate,
} from "@/api/app/dataModel/erModel";
import { getByTableName } from "@/api/app/dataModel/entityModel";
// tableName
export default {
  name: "erAddOrEditModal",
  dicts: ["pt_app_er_model_structure"],
  components: {
    settingMainTable,
  },
  props: {
    open: {
      type: Boolean,
      default: false,
    },
    close: {
      type: Function,
      default: () => {},
    },
    row: {
      type: String,
      default: "",
    },
    appId: {
      type: String,
      default: "",
    },
  },
  data() {
    return {
      settingTableOPen: false,
      form: {},
      tableData: [],
      rowData: undefined,
      btnLoading: false,
      rules: {
        name: [
          { required: true, message: "请输入ER模型名称", trigger: "blur" },
        ],
        mark: [
          { required: true, message: "请输入ER模型标识", trigger: "blur" },
          {
            pattern: /^[^\s\u4e00-\u9fa5/\\]+$/,
            message: "ER模型标识不能包含汉字、斜线、空格",
            trigger: "blur",
          },
        ],
      },
    };
  },

  async mounted() {
    if (this.row) {
      const res = await appErModelDetail(this.row.id);
      if (res.code == 200) {
        this.form = res.data?.erModelVo;
        this.tableData = res.data?.objectRelations;
        this.delData(this.tableData);
      }
    }
  },

  methods: {
    delData(list) {
      function traverse(nodes) {
        nodes.forEach((node) => {
          node.formComment = node.formName;
          if (node.optionsChild) {
            node.optionsChild = JSON.parse(node.optionsChild);
          }
          if (node.optionsMain) {
            node.optionsMain = JSON.parse(node.optionsMain);
          }
          if (node.children?.length) {
            traverse(node.children);
          }
        });
      }
      traverse(list);
    },
    async flattenTree(tree) {
      let result = [];
      function traverse(nodes) {
        nodes.forEach((node) => {
          result.push(node);
          if (node.children) {
            traverse(node.children);
          }
        });
      }
      traverse(tree);
      return result;
    },
    setParentId(nodes) {
      nodes.forEach((node) => {
        if (node.children) {
          node.children.forEach((child) => {
            child.parentId = node.uuId;
            child.parentFormCode = node.formCode;
            this.setParentId([child]);
          });
        }
      });
    },
    handleAddChild(row) {
      this.settingTableOPen = true;
      this.rowData = row;
    },
    handleSubmit() {
      this.$refs["form"].validate(async (valid) => {
        if (valid) {
          if (!this.tableData?.length) {
            return this.$message.error("请添加主表数据");
          }
          const params = {
            erModelBo: {
              id:   this.form?.id,
              name: this.form?.name,
              mark: this.form?.mark,
              appId: this.appId,
              formCode: this.tableData[0]?.formCode,
              modelStructure: this.tableData[0]?.children?.[0]?.relation,
            },
            objectRelations: [],
          };
          const nodeMap = {};
          this.tableData.forEach((node) => {
            nodeMap[node.id] = node;
          });
          this.setParentId(this.tableData);
          let fletTable = await this.flattenTree(this.tableData);
          fletTable.forEach((item) => {
            params.objectRelations.push({
              id: !!this.row ? item.id :  undefined,
              uuId: item.uuId,
              formCode: item.formCode,
              formName: item.formComment,
              relation: item.relation,
              parentId: item.parentId,
              parentFormCode: item.parentFormCode,
              mainForeignKey: item.mainForeignKey,
              subForeignKey: item.subForeignKey,
              optionsMain: JSON.stringify(item.optionsMain),
              optionsChild: JSON.stringify(item.optionsChild),
            });
          });
          if (!this.row) {
            const res = await appErModelAdd(params);
            if (res.code === 200) {
              this.$message.success("新增成功");
              this.close();
            }
          } else {
            const res = await appErModelUpdate(params);
            if (res.code === 200) {
              this.$message.success("编辑成功");
              this.close();
            }
          }
        }
      });
    },
    handleDelete(row, type) {
      if (type) {
        row.mainForeignKey = undefined;
        row.subForeignKey = undefined;
        return;
      }
      this.$confirm("此操作将永久删除该条数据, 是否继续?", "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
      })
        .then(() => {
          this.removeNodeById(this.tableData[0], row.id);
        })
        .catch(() => {});
    },
    closeModel() {
      this.settingTableOPen = false;
    },
    async settingTableClose(type, row) {
      row.formCode = row.tableName;
      row.formComment = row.remark;
      if (type === "1") {
        if (!this.rowData) {
          row.parentId = "0";
          row.uuId = uuid.v1();
          this.tableData = [row];
        } else {
          const fletTable = await this.flattenTree(this.tableData);
          let isPass = true;
          fletTable.forEach((item) => {
            if (item.formCode === row.formCode) {
              isPass = false;
            }
          });
          if (!isPass) {
            this.$message.error(
              `存在重复表:[${row.formCode}/${row.formComment}]`
            );
            this.closeModel();
            return;
          }
          this.btnLoading = true;
          row.relation = "one_to_many";
          const parentRes = await getByTableName({
            tableName: row.formCode,
          });
          row.optionsChild = parentRes.data?.formFields || [];
          const childRes = await getByTableName({
            tableName: this.rowData.formCode,
          });
          this.btnLoading = false;
          row.optionsMain = childRes.data?.formFields || [];
          row.uuId = uuid.v1();
          if (!this.rowData?.children?.length) {
            this.rowData.children = [row];
          } else {
            this.rowData.children.push(row);
          }
          this.tableData = JSON.parse(JSON.stringify(this.tableData));
        }
        this.closeModel();
      }
    },
    async flattenTree(tree) {
      let result = [];
      function traverse(nodes) {
        nodes.forEach((node) => {
          result.push(node);
          if (node.children) {
            traverse(node.children);
          }
        });
      }
      traverse(tree);
      return result;
    },
    removeNodeById(tree, idToRemove) {
      const _this = this;
      function traverse(node) {
        if (node.children?.length) {
          for (let i = 0; i < node.children.length; i++) {
            const child = node.children[i];
            if (child.id === idToRemove) {
              node.children.splice(i, 1);
              return true;
            }
            const removed = traverse(child);
            if (removed) {
              return true;
            }
          }
        }
        if(node.parentId === '0'){
          _this.tableData = []
          return
        }
        return false;
      }
      traverse(tree);
    },
  },
};
</script>

<style lang="scss" scoped>
.erAddOrEditModal {
  .box {
    width: 100%;
    display: grid;
    // grid-template-rows: 50% 50%;
    grid-template-columns: 1fr 1fr;
    // grid-template-rows: auto auto;
    grid-column-gap: 8px;
    grid-row-gap: 8px;
    justify-items: stretch;
    align-items: start;
  }
  .table {
    margin-top: 5px;
  }
}
</style>
